home *** CD-ROM | disk | FTP | other *** search
- /*
- HEADER: CUG999.11;
- TITLE: GED (nee QED) screen editor -- part 2;
- DATE: 12/19/86;
-
- DESCRIPTION: "Text changing routines for the GED editor. Eg,
- movechar, insertchar.";
- SYSTEM: MS-DOS;
- FILENAME: GED2.C;
- AUTHORS: G. Nigel Gilbert, James W. Haefner, Mel Tearle, G. Osborn;
- COMPILERS: DeSmet C;
- */
-
- /*
- e/qed/ged screen editor
-
- (C) G. Nigel Gilbert, MICROLOGY, 1981
- August-December 1981
-
- Modified: Aug-Dec 1984: BDS-C 'e'(vers 4.6a) to 'qe' (J.W. Haefner)
- March 1985: BDS-C 'qe' to DeSmet-C 'qed' (J.W. Haefner)
- May 1986: converted to ged - Mel Tearle
-
- FILE: hist.c
-
- FUNCTIONS: undo, pop
-
- PURPOSE: perform text changing commands
-
- */
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include "ged.h"
-
-
- /* undoes edits on current line and then from history
- */
- undo()
- {
- int l, inicnt, c;
-
- puttext();
- if ( histcnt == 0 ) {
- error( " Nothing to undo " );
- return;
- }
- inicnt = histcnt;
- c = OOPSKEY; /* do the first one for free */
-
- do {
- vbord1 = MAXINT;
- vbord2 = 0;
- blocking = NO;
-
- switch (c) {
- case OOPSKEY:
- case '-': /* ctrl key not requeired */
- case '_':
- if (histcnt > 0) {
- do {
- l = undoredo(-1); /* pre decrements histptr */
- }
- while ( histcnt > 0 && history[histptr].histcomm ==
- history[ (histptr-1 >= 0) ? histptr-1 : HISTLEN-1 ].histcomm );
-
- hshow(l);
-
- }
- else {
- error("Can't undo more. Redo or escape. Escape obliterates redo.");
- }
- break;
-
- case '=':
- case '+': /* same key */
- if (histcnt < inicnt) {
- do {
- l = undoredo(1); /* post increments histptr */
- }
- while ( histcnt < inicnt && history[histptr].histcomm ==
- history[ (histptr-1 >= 0) ? histptr-1 : HISTLEN-1 ].histcomm );
-
- hshow(l);
- }
- else {
- error("Can't redo future. Now in edit mode.");
- resetpcursor();
- while (chkbuf() == 0)
- ;
- goto leave;
- }
- break;
-
- default:
- error("Bad key. ^- to undo more, + or = to redo, <esc> to resume editing");
- break;
- }
- }
- while ( (c = getkey()) != ESCKEY);
-
- leave:;
- blocking = NO;
- putpage();
- blankedmess = YES;
- return;
- }
-
-
- /* local function */
-
- hshow(l)
- int l;
- {
- int i;
-
- /* leave room for the line number. not an error, but show in reverse field */
- hstart(FNPOS);
- error1(" - undo, +/= redo; or <esc> ");
- show_time(1);
-
- if (vbord2 >= vbord1)
- blocking=TRUE;
-
- /* moveline requires that the existing physical display agree with memory.
- * They aren't the same at this point if lines within the active display
- * area have been changed. A complete rewrite is necessary.
- */
- charn = offset + (offset>0);
- /* the preferred cursor position is the one that does not cause scrolling */
- cursory += l - cline;
- /* re-optimize the cursor if the new location is off-screen */
- if (cursory > SHEIGHT || cursory < topline)
- cursory = topline + (SHEIGHT - topline)/2;
- /* but it is more important to see the whole block */
- i = cline;
- cline = l;
- calp();
- cline = i;
- if (vbord2 >= plast)
- cursory += plast - vbord2 -1; /* limit checked in calp() */
-
- plast = -1;
- moveline(l-cline);
- return;
- }
- /* --------------------------------------- */
- /* local function
- * direc = 1 to redo, -1 to undo.
- */
- int undoredo(direc)
- int direc;
- {
- int l, hpage, hoff;
-
- if (direc < 0) { /* post increment for redo */
- if ( --histptr < 0 )
- histptr = ( HISTLEN - 1 );
- histcnt--;
- }
-
- storehist = NO;
-
- l = history[histptr].histline;
- hpage = history[histptr].histp.page;
- hoff = history[histptr].histp.moffset;
-
- /* the following comments apply to an undo step. The same code is executed
- * for the redo, but then the undo/redo roles change. The function is
- * fully symmetrical between redo/undo, and except for a wasted byte
- * in the inject() is indefinately reversible.
- */
-
- switch ( history[histptr].histtype ) {
-
- case HISTINSERT:
- history[histptr].histp.moffset = tp[l].moffset; /* prepare for redo */
- history[histptr].histp.page = tp[l].page; /* prepare for redo */
- history[histptr].histtype = HISTDELETE; /* prepare for redo */
- deltp(l,1); /* undo */
- if (l <= vbord2)
- vbord2--;
- break;
- case HISTDELETE:
- inject(l-1,""); /* undo */
- tp[l].moffset = hoff; /* undo */
- tp[l].page = hpage; /* undo */
- history[histptr].histtype = HISTINSERT; /* prepare for redo */
- if (vbord2 >= l)
- vbord2++;
- if (l > vbord2)
- vbord2 = l;
- if (l < vbord1)
- vbord1 = l;
- break;
- case HISTREPLACE:
-
- history[histptr].histp.moffset = tp[l].moffset; /* prepare for redo */
- history[histptr].histp.page = tp[l].page; /* prepare for redo */
- tp[l].page = hpage; /* undo */
- tp[l].moffset= hoff; /* undo */
-
- if (l > vbord2)
- vbord2 = l;
- if (l < vbord1)
- vbord1 = l;
- break;
- }
- if (direc > 0) {
- if (++histptr >= HISTLEN)
- histptr = 0;
- histcnt++;
- }
-
- return l;
- }
- /* --------------------------------------- */
-
- /* pop the last deleted line from the history buffer.
- * This is a prelimenary implementation of stack operations and is
- * something of a kludge. The stack needs its own table. It can
- * use the text of the lines in the histroy buffer, though.
- * This "stack" will be overwritten after 100 editing operations.
- * Pops can be undone, so a different area of the data base used here
- * is modifed by addhistory() when a pop is performed.
- * Editing which occurs later than the pop can be undone without conflict,
- * provided there is not too much of it.
- */
-
- pop(mode)
- int mode;
- {
- int onpage; /* flag for changes to current screen */
- int l, slot;
- int h0, h1, h2;
- char *ptr;
- char *gethist();
-
- puttext(); /* must be done before the stack test */
- if ( stkcnt == 0 ) {
- error( " Stack empty " );
- return;
- }
- h0 = stkptr;
- h1 = stkcnt;
- h2 = 0;
- do {
- if ( --stkptr < 0 )
- stkptr = ( HISTLEN - 1 );
- stkcnt--;
- ptr = gethist(history[stkptr].histp.page,history[stkptr].histp.moffset);
- switch ( history[stkptr].histtype ) {
- case HISTREPLACE:
- break;
- case HISTINSERT:
- break;
- case HISTDELETE:
- h2 = 1;
- break;
- }
-
- }
- while ( !h2 && stkcnt && history[stkptr].histcomm ==
- history[( stkptr-1 < 0 ? HISTLEN-1 : stkptr-1) ].histcomm );
- if (mode == 1) {
- stkptr = h0; /* copy and pop. restore to original state. */
- stkcnt = h1;
- }
- if (!h2)
- error( " Stack empty " );
- else {
- vbord1=cline;
- vbord2=cline;
- blocking=TRUE;
- scrolldown(cursory);
- sync(offset + (offset>0));
- putline(cline, cursory, ptr);
- putlineno(cline); /* new col no */
- resetpcursor();
-
- /* do the slow work while waiting for a keystroke, otherwise the next
- operation is delayed
- */
- inject(cline-1,ptr);
- calp(); /* plast may have changed */
- while (chkbuf()==0) /* wait for any key */
- ;
-
- blocking = FALSE;
- gettext( cline, charn );
- putline(cline, cursory, NULL);
- }
- return;
-
- }
-